package com.bluexmicro.ota;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.bluetooth.le.ScanResult;
import android.content.Context;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.bluexmicro.android.ota.OtaManager;
import com.bluexmicro.android.ota.OtaParamHelper;
import com.bluexmicro.android.ota.OtaTransaction;
import com.bluexmicro.android.ota.SingleTransactionTaskCallback;
import com.bluexmicro.android.ota.TransactionLaunchCallback;
import com.bluexmicro.android.ota.entity.OtaCallback;
import com.bluexmicro.android.ota.entity.OtaState;
import com.bluexmicro.android.ota.entity.OtaTask;

import java.io.File;
import java.math.BigInteger;
import java.util.List;

/**
 * 1. 在你的 root build.gradle 添加 maven { url 'https://jitpack.io' }
 * 2. implementation 'com.gitee.bluexmicro:Android-OTA-Library:1.0.5' //replace latest version
 */
public class JavaExample {

    @NonNull
    private final OtaManager manager;

    ///////////////////////////////////////////////////////////////////////////
    // 构造函数
    ///////////////////////////////////////////////////////////////////////////


    /**
     * @param device   当前宿主正在连接对象
     * @param fastMode 快速模式，请与软件工程师确认！<<<<<<<<<<
     */
    public void test(Context context, BluetoothDevice device, Boolean fastMode) {
        //获取device对应的已连接的对象，
        OtaTransaction.Companion.shared().startTransaction(context, device, fastMode, new TransactionLaunchCallback() {
            @Override
            public void onResult(boolean result, @Nullable String errorMessage) {
                if (result) {
                    //表盘1
                    // sendFaceData(otaTask1);

                    //表盘2
                    //sendFaceData(otaTask2);

                    //表盘3
                    //sendFaceData(otaTask3);

                    //...
                    // 表盘n
                    //sendFaceData(otaTaskN);
                }else{
                    //连接失败
                }
            }
        });
    }

    //发送表盘数据
    private void sendFaceData(OtaTask task) {
        OtaTransaction.Companion.shared().execute(task, false, new SingleTransactionTaskCallback() {
            @Override
            public void onProgress(float value) {
                //进度 0～1f
            }

            @Override
            public void onResult(boolean result, @Nullable String errorMessage) {
                //结果
            }
        });

        //如果这个设备不再使用，看情况释放连接(设备会断开并重启)
        //OtaTransaction.Companion.shared().endTransaction(fastMode);
    }

    public JavaExample(@NonNull Context context, @NonNull BluetoothDevice device) {
        manager = new OtaManager(context, device);
    }

    public JavaExample(@NonNull Context context, @NonNull String macAddress) {
        BluetoothManager manager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);
        if (manager == null) throw new IllegalArgumentException("蓝牙不可用");
        BluetoothAdapter adapter = manager.getAdapter();
        if (adapter == null) throw new IllegalArgumentException("蓝牙未开启或者不可用");
        if (!BluetoothAdapter.checkBluetoothAddress(macAddress)) {
            throw new IllegalArgumentException("蓝牙地址格式不正确");
        }
        BluetoothDevice device = adapter.getRemoteDevice(macAddress);
        if (device == null) {
            //1. 在此之前宿主app未进行扫描或者扫描时未发现此设备
            //2. 权限、位置信息等
            throw new IllegalArgumentException("找不到设备");
        }
        this.manager = new OtaManager(context, device);
    }

    public JavaExample(@NonNull Context context, @NonNull ScanResult scanResult) {
        manager = new OtaManager(context, scanResult.getDevice());
    }

    ///////////////////////////////////////////////////////////////////////////
    // 开始OTA
    ///////////////////////////////////////////////////////////////////////////

    OtaCallback callback = new OtaCallback() {
        @Override
        public void onInitialError(@NonNull String errorMessage) {
            //连接设备时发生的错误
        }

        @Override
        public void onStateChanged(@NonNull OtaState state) {
            //当前任务的状态
            boolean hasResult = state.hasResult(); // 数据是否发送结束, 否（正在传输数据中）
            state.inProgress();//正在传输数据中
            float progress = state.progress; // 0.0~1.0, 传输进度
            int index = state.index; //任务索引，代表当前正在升级哪一任务
        }

        @Override
        public void onFinish() {
            // 任务结束。 任务状态, 请查看 => onStateChanged
        }
    };

    void startOta(OtaTask task) {
        manager.startOta(task, callback);
    }

    void startFastOta(List<OtaTask> tasks) {
        manager.startFastOta(tasks, callback);
    }

    //中途取消
    void cancel() {
        manager.cancel();
    }

    //是否资源，执行后manager不可用，需重新创建对象。一般用于离开OTA页面时
    void release() {
        manager.release();
    }

    ///////////////////////////////////////////////////////////////////////////
    // 关于参数的初始化
    ///////////////////////////////////////////////////////////////////////////

    /**
     * @param file       从服务器下载的（获取嵌入式工程师提供的）固件（firmware.bin）
     * @param hexAddress 16进制地址（example：E33000），如果为null，则代表默认地址，（从服务器获取，或者询问你们的嵌入式工程师）
     */
    OtaTask buildOtaTask(File file, @Nullable String hexAddress) {
        byte[] data = OtaParamHelper.INSTANCE.loadBinData(file);
        if (data == null) return null;
        BigInteger address;
        try {
            address = new BigInteger(hexAddress, 16);
        } catch (Exception ignore) {
            // hexAddress 格式不对
            address = null;
        }
        return new OtaTask(data, address);
    }

    /**
     * @param bytes      从服务器下载的数据
     * @param hexAddress 16进制地址（example：E33000），如果为null，则代表默认地址，（从服务器获取，或者询问你们的嵌入式工程师）
     */
    OtaTask buildOtaTask(byte[] bytes, @Nullable String hexAddress) {
        BigInteger address;
        try {
            address = new BigInteger(hexAddress, 16);
        } catch (Exception ignore) {
            // hexAddress 格式不对
            address = null;
        }
        return new OtaTask(bytes, address);
    }

    BluetoothDevice getDeviceByMacAddress(Context context, @NonNull String macAddress) {
        return OtaParamHelper.INSTANCE.getBluetoothDevice(context, macAddress);
    }

}
